package com.tencent.txcc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.tencent.txcc.ESService;
import com.tencent.txcc.MediaService;
import com.tencent.txcc.domain.*;
import com.tencent.txcc.dto.*;
import com.tencent.txcc.enums.GlobleExceptionCode;
import com.tencent.txcc.mapper.*;
import com.tencent.txcc.result.JSONResult;
import com.tencent.txcc.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.tencent.txcc.util.AssertUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author director
 * @since 2022-10-07
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private ICourseDetailService courseDetailService;

    @Autowired
    private ICourseMarketService courseMarketService;

    @Autowired
    private ICourseResourceService courseResourceService;

    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private ESService esService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ICourseChapterService courseChapterService;

    @Autowired
    private MediaService mediaService;



    @Override
    public void save(CourseDto courseDto) {
        Course course = courseDto.getCourse();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        CourseResource courseResource = courseDto.getCourseResource();
        List<Long> teacherIds = courseDto.getTeacherIds();


        // 判断课程是否重名
        Course courseDemo = selectByName(courseDto.getCourse().getName());
        AssertUtil.isNull(courseDemo, GlobleExceptionCode.CLASS_NAME_IS_SAME);

        // 添加课程
        Long courseId = saveCourse(course, teacherIds);

        // 添加课程明细
        courseDetail.setId(courseId);
        courseDetailService.insert(courseDetail);

        // 添加课程市场
        courseMarket.setId(courseId);
        courseMarketService.insert(courseMarket);

        // 添加课程资源
        courseResource.setCourseId(courseId);
        courseResourceService.insert(courseResource);

        // 初始化课程统计
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(courseId);
        courseSummaryService.insert(courseSummary);

        // 新增课程讲师
        courseMapper.insertTeacher(courseId, teacherIds);

        // 給课程对应的类型下的课程数量加1
        courseTypeMapper.updateCourseCount(course.getCourseTypeId());
    }

    @Override
    public void patchDel(List<Long> ids) {
        courseMapper.patchDel(ids);
    }





    @Override
    public void onLineCourse(Long id) {
        // 通过传入的id找到这个课程
        Course course = courseMapper.selectById(id);
        // 判断课程不能为空
        AssertUtil.isNotNull(course, GlobleExceptionCode.PARAM_IS_NULL);
        // 状态查看是否修改过了,
        if(course.getStatus() == Course.STATUS_ON_LINE){
            return;
        }
        // 修改课程状态为上架
        course.setStatus(Course.STATUS_ON_LINE);
        updateById(course);


        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course, courseDoc);

        // 将CourseMarket的值传到courseDoc中
        CourseMarket courseMarket = courseMarketService.selectById(id);
        BeanUtils.copyProperties(courseMarket, courseDoc);
        String charge = courseMarket.getCharge() == 1 ? "免费" : "收费";
        courseDoc.setCharge(charge);


        // 将CourseResource的值传到courseDoc中
        CourseResource courseResource = getSelectByCourseId(id);
        BeanUtils.copyProperties(courseResource, courseDoc);

        // 将CourseSummary的值传到courseDoc中
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        BeanUtils.copyProperties(courseSummary, courseDoc);

        // 将CourseType的值传到courseDoc中
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseDoc.setName(courseType.getName());

        // 通过openFeign将courseDoc传给es
        esService.courseEsAdd(courseDoc);

        // 发送MQ消息
        // 通过手机号发送消息
        getSendSmsMessage(course);

        // 通过收藏发送消息


    }

    @Override
    public void offLineCourse(Long id) {
        // 通过传入的id找到这个课程
        Course course = courseMapper.selectById(id);
        // 判断课程不能为空
        AssertUtil.isNotNull(course, GlobleExceptionCode.PARAM_IS_NULL);
        // 状态查看是否修改过了,
        if(course.getStatus() == Course.STATUS_OFF_LINE){
            return;
        }
        // 修改课程状态为上架
        course.setStatus(Course.STATUS_OFF_LINE);
        updateById(course);
        esService.courseEsDel(id);

    }

    @Override
    public CourseDetailVo getDetail(Long courseId) {
        // 1.业务校验
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course, GlobleExceptionCode.PARAM_IS_NULL);
        boolean boo = Course.STATUS_ON_LINE == course.getStatus();
        AssertUtil.isTrue(boo, GlobleExceptionCode.PARAM_IS_NULL);
        // 2.查询课程相关数据，进行封装
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        List<Teacher> teachers = courseMapper.selectTeacherById(courseId);
        Wrapper<CourseChapter> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", courseId);
        List<CourseChapter> courseChapters = courseChapterService.selectList(wrapper);

        Map<Long, CourseChapter> courseChapterMap = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));

        JSONResult jsonResult = mediaService.getMediaFileByCourseId(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobleExceptionCode.ERROR);
        Object data = jsonResult.getData();
        AssertUtil.isNotNull(data, GlobleExceptionCode.ERROR);

        List<MediaFile> mediaFiles = JSON.parseArray(data.toString(), MediaFile.class);
        mediaFiles.forEach(m ->{
            m.setFileUrl("");
            CourseChapter courseChapter = courseChapterMap.get(m.getChapterId());
            if (courseChapter != null){
                courseChapter.getMediaFiles().add(m);
            }
        });
        return new CourseDetailVo(course, courseDetail, courseMarket, teachers, courseChapters, courseSummary);
    }






    @Override
    public CourseInfoVo getInfo(String courseIds) {
        Set<Long> collect = Arrays.stream(courseIds.split(","))
                                  .filter(id -> !StringUtils.isEmpty(id))
                                  .map(id -> Long.valueOf(id))
                                  .collect(Collectors.toSet());
        boolean boo = collect.size() == courseIds.split(",").length;
        AssertUtil.isTrue(boo, GlobleExceptionCode.ERROR);
        List<Long> courseIdsList = collect.stream().collect(Collectors.toList());
        List<Course> courses = selectBatchIds(courseIdsList);
        AssertUtil.isNotNull(courses, GlobleExceptionCode.ERROR);
        Map<Long, CourseMarket> courseMarketMap = courseMarketService.selectBatchIds(courseIdsList).stream().collect(Collectors.toMap(CourseMarket::getId, courseMarket -> courseMarket));
        CourseInfoVo courseInfoVo = new CourseInfoVo();
        List<CourseOrderVo> courseOrderVos = new ArrayList<>();

        courses.forEach(course ->{
            CourseOrderVo courseOrderVo = new CourseOrderVo();
            boolean isOK = Course.STATUS_ON_LINE == course.getStatus();
            AssertUtil.isTrue(isOK, GlobleExceptionCode.ERROR);
            CourseMarket courseMarket = courseMarketMap.get(course.getId());
            AssertUtil.isNotNull(courseMarket, GlobleExceptionCode.ERROR);
            courseOrderVo.setCourse(course);
            courseOrderVo.setCourseMarket(courseMarket);
            courseInfoVo.setTotalAmount(courseInfoVo.getTotalAmount().add(courseMarket.getPrice()));
            courseOrderVos.add(courseOrderVo);
        });
        courseInfoVo.setCourseInfos(courseOrderVos);

        return courseInfoVo;
    }





    private CourseResource getSelectByCourseId(Long id) {
        Wrapper<CourseResource> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", id);
        CourseResource courseResource = courseResourceService.selectOne(wrapper);
        return courseResource;
    }


    private void getSendSmsMessage(Course course) {
        SendOnLineMessageDto sendOnLineMessageDto = new SendOnLineMessageDto();
        sendOnLineMessageDto.setTitle("课程发布");
        sendOnLineMessageDto.setContent("亲爱的用户您好，最新课程 <a href='localhost:6002/detail.html?courseId="+course.getId()+"'> "+ course.getName() +" </a> 发布啦，点击课程了解详情");
        List<UserMessageDto> userMessageDtos = Arrays.asList(
                new UserMessageDto(41L, "18244444111"),
                new UserMessageDto(42L, "18944444444")
        );
        sendOnLineMessageDto.setUserMessageDto(userMessageDtos);
        String str = JSON.toJSONString(sendOnLineMessageDto);
        rocketMQTemplate.sendOneWay("smsmessage-topic:smsmessage-tag", str);
    }


    private Course selectByName(String name) {
        EntityWrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);
        return selectOne(wrapper);
    }

    private Long saveCourse(Course course, List<Long> teacherIds) {
        course.setStatus(Course.STATUS_OFF_LINE);
        course.setLoginId(3L);
        course.setLoginUserName("13330964748");

        String teacherName = teacherService.selectBatchIds(teacherIds).stream().map(teacher -> teacher.getName()).collect(Collectors.joining(","));

        course.setTeacherNames(teacherName);
        insert(course);
        return course.getId();
    }
}